#include "aligncommand.h"
#include "document.h"

#include <QDebug>

namespace SymbolEditor
{

    AlignCommand::AlignCommand(UndoCommand *parent):
        UndoCommand(parent)
    {
    }

    AlignCommand::~AlignCommand()
    {
    }

    void AlignCommand::setItems(const QList<quint64> &idList)
    {
        m_itemIdList = idList;
    }

    void AlignCommand::setAlignment(Qt::Alignment alignment)
    {
        m_alignment = alignment;
    }

    QRectF AlignCommand::alignmentRect(const Item *item)
    {
        // FIXME: Should be return item->mapToModel(item->outline()).boundingRect();
        QTransform xform;
        xform.translate(item->position().x(), item->position().y());
        xform.rotate(item->rotation());
        if (item->isXMirrored())
        {
            xform.scale(-1, 1);
        }
        if (item->isYMirrored())
        {
            xform.scale(1, -1);
        }
        return xform.map(item->outline()).boundingRect();
    }

    void AlignCommand::undo()
    {
        if (m_itemIdList.count() < 2)
        {
            return;
        }

        for (int i = 1; i < m_itemIdList.count(); i++)
        {
            auto itemId = m_itemIdList.value(i);
            auto item = document()->item(itemId);
            auto delta = m_deltaMap.value(itemId);
            auto pos = item->position() - delta;
            document()->setItemProperty(itemId, PositionProperty, pos);
        }
    }

    void AlignCommand::redo()
    {
        setText(QString("Align %1 item(s)").arg(m_itemIdList.count()));

        if (m_itemIdList.count() < 2)
        {
            return;
        }

        auto refItemId = m_itemIdList.first();
        auto refItem = document()->item(refItemId);
        auto refRect = alignmentRect(refItem);

        for (int i = 1; i < m_itemIdList.count(); i++)
        {
            auto itemId = m_itemIdList.value(i);
            auto item = document()->item(itemId);
            auto itemRect = alignmentRect(item);

            QPointF delta;
            switch (m_alignment)
            {
                case Qt::AlignTop:
                    delta.setY(refRect.top() - itemRect.top());
                    break;
                case Qt::AlignVCenter:
                    delta.setY(refRect.center().y() - itemRect.center().y());
                    break;
                case Qt::AlignBottom:
                    delta.setY(refRect.bottom() - itemRect.bottom());
                    break;
                case Qt::AlignLeft:
                    delta.setX(refRect.left() - itemRect.left());
                    break;
                case Qt::AlignHCenter:
                    delta.setX(refRect.center().x() - itemRect.center().x());
                    break;
                case Qt::AlignRight:
                    delta.setX(refRect.right() - itemRect.right());
                    break;
                default:
                    break;
            }

            m_deltaMap.insert(itemId, delta);
            auto pos = item->position() + delta;
            document()->setItemProperty(itemId, PositionProperty, pos);
        }
    }

}
